﻿using mozhi.smarterp.Finance.Accounts.Repository;
using mozhi.smarterp.Finance.Enums;
using mozhi.smarterp.Finance.Querys;
using mozhi.smarterp.Finance.Reports.Repository;
using Mozhi.Abp.Core.Extensions;
using System;
using System.Collections;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using Volo.Abp;
using Volo.Abp.Guids;

namespace mozhi.smarterp.Finance.Reports
{
    public class FinancialReportItemAppService : FinanceAppService, IFinancialReportItemAppService
    {
        private IFinancialReportItemRepository _repository;
        private IAccountRepository _accountRepository;
        private IGuidGenerator _guidGenerator;

        public FinancialReportItemAppService(IFinancialReportItemRepository repository , 
            IAccountRepository accountRepository , IGuidGenerator guidGenerator)
        {
            _repository = repository;
            _accountRepository = accountRepository;
            _guidGenerator = guidGenerator;
        }

        public async Task<List<FinancialReportItemDto>> FindAsync(FinancialReportItemQuery query)
        {
            var reportItems = await _repository.FindAsync(query);

            var result = ObjectMapper.Map<List<FinancialReportItem>, List<FinancialReportItemDto>>(reportItems);

            await LoadAccountInfoAsync(result);

            return result;
        }

        public async Task<FinancialReportItemDto> GetAsync(Guid id)
        {
            var reportItem = await _repository.FindAsync(id);

            var result = ObjectMapper.Map<FinancialReportItem, FinancialReportItemDto>(reportItem);

            await LoadAccountInfoAsync(new List<FinancialReportItemDto>() { result });

            return result;
        }

        public async Task<List<FinancialReportItemDto>> UpdateAsync(List<FinancialReportItemUpdateDto> dtos)
        {
            if (dtos == null || dtos.Count == 0)
                throw new UserFriendlyException("报表项不能为空", "100000");

            var reportItems = new List<FinancialReportItem>();

            foreach (var dto in dtos)
            {
                var reportItem = await _repository.GetAsync(dto.Id);

                if (reportItem == null)
                    throw new UserFriendlyException($"报表项：{dto.Id}不存在", "100000");


                if (dto.Settings != null || dto.Settings.Count == 0)
                    continue;

                var settings = new List<FinancialReportItemSetting>();


                foreach(var dtoSetting in dto.Settings)
                {
                    var setting = new FinancialReportItemSetting(dtoSetting.Id.HasValue ? dtoSetting.Id.Value : _guidGenerator.Create(), 
                        reportItem.Id, reportItem.Code, dtoSetting.CalculateTarget, dtoSetting.Operator, dtoSetting.Precondition);

                    settings.Add(setting);
                }

                reportItem.ChangeItems(settings);

                reportItem = await _repository.UpdateAsync(reportItem);

                reportItems.Add(reportItem);
            }

            var result = ObjectMapper.Map<List<FinancialReportItem>, List<FinancialReportItemDto>>(reportItems);

            await LoadAccountInfoAsync(result);

            return result;
        }

        public async Task<bool> DeleteAsync(Guid id, List<Guid> settingIds)
        {
            var reportItem = await _repository.GetAsync(id);

            if(reportItem==null)
                throw new UserFriendlyException($"报表项：{id}不存在", "100000");

            var matchSettings = reportItem.Settings.Where(x=>!settingIds.Contains(x.Id)).ToList();

            reportItem.ChangeItems(matchSettings);

            return true;
        }

        public async Task LoadDefaultDataAsync(AccountingStandardType accountingStandard)
        {
            var defaultReportItems = await _repository.GetDefaultReportItemsAsync(accountingStandard);

            var oldReportItems = await _repository.FindAsync(new FinancialReportItemQuery());

            if (oldReportItems.Count > 0)
                await _repository.DeleteAsync(oldReportItems);

            await _repository.InsertAsync(defaultReportItems);
        }

        #region
        private async Task LoadAccountInfoAsync(List<FinancialReportItemDto> reportItems)
        {
            //if (reportItems.Count == 0)
            //    return;

            //var accountCodes = reportItems.Where(x => x.Settings != null).Select(x => x.Settings).ToList().Join().Where(x => !x.CalculateTarget.IsNullOrEmpty()).Select(x => x.CalculateTarget).Distinct().ToList();

            //var acounts = await _accountRepository.FindAsync(new AccountQuery() { Codes = accountCodes });

            //if (acounts.Count == 0)
            //    return;

            //foreach (var reportItem in reportItems)
            //{
            //    var settings = reportItem.Settings;

            //    if (settings == null || settings.Count == 0)
            //        continue;

            //    settings.ForEach(setting =>
            //    {
            //        var match = acounts.FirstOrDefault(x => x.Code == setting.CalculateTarget);

            //        setting.CalculateTargetId = match?.Id;
            //        setting.CalculateTargetName = match?.FullName;
            //    });
            //}
            throw new NotImplementedException();
        }
        #endregion
    }
}
